/*
 *程序名：crtsurfdata1.cpp 
 *本程序用于生成全国气象站点观测数据
*/
#include "_public.h"
CPActive PActive;

// 	全国气象站点参数结构体
struct st_stcode{
	char provname[31];
	char obtid[11];
	char obtname[31];
	double lat;
	double lon;
	double height;
};
vector<struct st_stcode> vstcode;
bool LoadSTCode(const char *inifile);

// 全国气象站点分钟观测数据结构体
struct st_surfdata
{
  char obtid[11];      // 站点代码。
  char ddatetime[21];  // 数据时间：格式yyyymmddhh24miss
  int  t;              // 气温：单位，0.1摄氏度。
  int  p;              // 气压：0.1百帕。
  int  u;              // 相对湿度，0-100之间的值。
  int  wd;             // 风向，0-360之间的值。
  int  wf;             // 风速：单位0.1m/s
  int  r;              // 降雨量：0.1mm。
  int  vis;            // 能见度：0.1米。
};
vector<struct st_surfdata> vsurfdata;
void CrtSurfData();
bool CrtSurfFile(const char *outpath,const char *datafmt);

// 观测数据时间：当前时间
char strddatetime[21];

CFile File;
CLogFile logfile(10);

void EXIT(int sig);		// 程序退出和信号2、15的处理函数

int main(int argc, char * argv[]){
	// help
	if((argc != 5) && (argc != 6)){
		cout << "invalid input" << endl;
		cout << "example: /project/idc1/bin/crtsurfdata1 /project/idc1/ini/stcode.ini /tmp/idc/surfdata /log/idc/crtsurfdata1.log xml,json.csv" << endl;
	
		cout << "inifile 全国气象站点参数文件名" << endl;
		cout << "outpath 全国气象站点数据文件存放目录" << endl;
		cout << "logfile 本程序运行的日志文件名" << endl;
		cout << "datafmt 生成数据文件的格式,支持xml,json和csv三种格式" << endl;
		cout << "datatime 可选参数，表示生成指定时间的数据和文件" << endl;

		return -1;
    }

	// 关闭全部的信号和输入输出
    // 设置信号,在shell状态下可用 "kill + 进程号" 正常终止些进程
    // 但请不要用 "kill -9 +进程号" 强行终止
    CloseIOAndSignal(true);
	signal(SIGINT, EXIT);		// SIGINT为2
	signal(SIGTERM, EXIT);		// SIGTERM为9


	if(logfile.Open(argv[3], "a+", false)==false){
		cout << "logfile.Open(" << argv[3] << ") failed" << endl;
		return -1;
    }

	logfile.Write("crtsurfdata1 start running.\n");
	PActive.AddPInfo(20, "crtsurfdata");

    // 这里插入业务代码
	if(LoadSTCode(argv[1])==false){
		return -1;
	}
	
	// 获取当前时间/输入时间，当作观测时间
	memset(strddatetime, 0, sizeof(strddatetime));
	if(argc == 5){
		LocalTime(strddatetime, "yyyymmddhh24miss");
	}
	else{
		STRCPY(strddatetime, sizeof(strddatetime), argv[5]);
	}
	

	CrtSurfData();

	if(strstr(argv[4], "xml") != 0){
		CrtSurfFile(argv[2], "xml");
	}
	if(strstr(argv[4], "json") != 0){
		CrtSurfFile(argv[2], "json");
	}
	if(strstr(argv[4], "csv") != 0){
		CrtSurfFile(argv[2], "csv");
	}
	logfile.WriteEx("crtsurfdata1 end.\n");
    
    return 0;
}

// 把站点参数文件中加载到vstcode容器中
bool LoadSTCode(const char *inifile){
	if(File.Open(inifile, "r") == false){
		logfile.Write("File.Open(%s) faild.\n", inifile);
		return false;
	}

	char strBuffer[301];
	CCmdStr CmdStr;				// 分割字符串的类
	struct st_stcode stcode;

	while(true){
		// 从站点参数中读取一行，如果读取完，跳出循环
		// memset(strBuffer, 0, sizeof(strBuffer));		// File类已实现初始化
		if(File.Fgets(strBuffer, 300, true) == false){
			break;
		}
		// 调试阶段启动，正式版本中注释
		// logfile.Write("=%s=\n", strBuffer);

		// 将读到的一行拆分
		CmdStr.SplitToCmd(strBuffer, ",", true);
		// 删除无效的行
		if(CmdStr.CmdCount()!=6){
			continue;
		}

		// 将站点参数的每个数据项保存到站点参数结构体中
		CmdStr.GetValue(0, stcode.provname, 30);
		CmdStr.GetValue(1, stcode.obtid, 30);
		CmdStr.GetValue(2, stcode.obtname, 30);
		CmdStr.GetValue(3, &stcode.lat);
		CmdStr.GetValue(4, &stcode.lon);
		CmdStr.GetValue(5, &stcode.height);

		// 将结构体放入站点参数容器
		vstcode.push_back(stcode);
	}
	// 关闭文件，在CFile类中析构函数中已经实现

	// 调试阶段启动，正式版本中注释
	// for(int i = 0; i < vstcode.size(); ++i){
	// 	logfile.Write("provname=%s\n", vstcode[i].provname);
	// }
	return true;
}

// 随机生成全国气象站点分钟观测数据，存放在vsurfdata容器中
void CrtSurfData(){
	// rand seed
	srand(time(0)); 

	struct st_surfdata stsurfdata;
	for(int i = 0; i < vstcode.size(); ++i){
		memset(&stsurfdata, 0, sizeof(stsurfdata));
		// 利用随机数填充分钟观测数据结构体
		strncpy(stsurfdata.obtid, vstcode[i].obtid, 10);
		strncpy(stsurfdata.ddatetime, strddatetime, 14);
		stsurfdata.t = rand()%351;
    	stsurfdata.p = rand()%265+10000;
    	stsurfdata.u = rand()%100+1;
    	stsurfdata.wd = rand()%360;
    	stsurfdata.wf = rand()%150;
    	stsurfdata.r = rand()%16;
    	stsurfdata.vis = rand()%5001+100000;

		// 将观测数据结构体放入分钟观测数据容器
		vsurfdata.push_back(stsurfdata);
	}
}

// 把容器vsurfdata中的全国气象站点分钟观测数据写入文件
bool CrtSurfFile(const char *outpath,const char *datafmt){
	// 拼接生成数据文件名称
	char strFileName[301];
	sprintf(strFileName, "%s/SURF_ZH_%s_%d.%s", outpath, strddatetime, getpid(), datafmt);

	if(File.OpenForRename(strFileName, "w")==false){
		logfile.Write("File.OpenForRename(%s) failed.\n", strFileName);
		return false;
	}
	// 判断文件格式
	if(strcmp(datafmt, "csv") == 0){
		File.Fprintf("站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度\n");
	}
	if(strcmp(datafmt, "xml") == 0){
		File.Fprintf("<data>\n");
	}
	if (strcmp(datafmt,"json")==0){
		File.Fprintf("{\"data\":[\n");
	}

	// 遍历分钟观测数据容器
	for(int i = 0; i < vsurfdata.size(); ++i){
		if(strcmp(datafmt, "csv") == 0){
			File.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n",\
        		vsurfdata[i].obtid,vsurfdata[i].ddatetime,vsurfdata[i].t/10.0,vsurfdata[i].p/10.0,\
        		vsurfdata[i].u,vsurfdata[i].wd,vsurfdata[i].wf/10.0,vsurfdata[i].r/10.0,vsurfdata[i].vis/10.0);
		}
		
		if(strcmp(datafmt, "xml") == 0){
			File.Fprintf("<obtid>%s</obtid><ddatetime>%s</ddatetime><t>%.1f</t><p>%.1f</p>"\
                   "<u>%d</u><wd>%d</wd><wf>%.1f</wf><r>%.1f</r><vis>%.1f</vis><endl/>\n",\
        			vsurfdata[i].obtid,vsurfdata[i].ddatetime,vsurfdata[i].t/10.0,vsurfdata[i].p/10.0,\
        			vsurfdata[i].u,vsurfdata[i].wd,vsurfdata[i].wf/10.0,vsurfdata[i].r/10.0,vsurfdata[i].vis/10.0);
		}

		if (strcmp(datafmt,"json")==0){
			File.Fprintf("{\"obtid\":\"%s\",\"ddatetime\":\"%s\",\"t\":\"%.1f\",\"p\":\"%.1f\","\
                   "\"u\":\"%d\",\"wd\":\"%d\",\"wf\":\"%.1f\",\"r\":\"%.1f\",\"vis\":\"%.1f\"}",\
        			vsurfdata[i].obtid,vsurfdata[i].ddatetime,vsurfdata[i].t/10.0,vsurfdata[i].p/10.0,\
        			vsurfdata[i].u,vsurfdata[i].wd,vsurfdata[i].wf/10.0,vsurfdata[i].r/10.0,vsurfdata[i].vis/10.0);
		
			if (i<vsurfdata.size()-1){
				File.Fprintf(",\n");
			}
			else{
				File.Fprintf("\n");
			}
		}
	}
	if (strcmp(datafmt,"xml")==0){
		File.Fprintf("</data>\n");
	}
	if (strcmp(datafmt,"json")==0){
		File.Fprintf("]}\n");
	}
	// sleep(10);
	// 关闭文件
	File.CloseAndRename();

	// 修改文件的时间属性
	UTime(strFileName, strddatetime);

	logfile.Write("generate data file %s successfully, data time %s, number of records %d\n",\
			strFileName,strddatetime,vsurfdata.size());

	return true;
}

void EXIT(int sig){
	logfile.Write("程序退出, sig = %d\n", sig);
	exit(0);
}